package service

import (
	"VideoManageSystem/internal/initConfig"
	"VideoManageSystem/internal/model"
	"errors"
	"go.uber.org/zap"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
	"strings"
)

// GetUserByAccount 根据账号查找用户
func GetUserByAccount(account string) (*model.User, error) {
	var user model.User
	err := initConfig.GormDb.Where("account = ?", account).First(&user).Error
	if err != nil {
		zap.L().Error("无法找到该用户", zap.Error(err))
		return nil, err
	}
	return &user, nil
}

// GetUserByID 根据ID查找用户
func GetUserByID(id string) (*model.User, error) {
	var user model.User
	err := initConfig.GormDb.Where("id = ?", id).First(&user).Error
	if err != nil {
		zap.L().Error("无法找到该用户", zap.Error(err))
		return nil, err
	}
	return &user, nil
}

// DeleteUserByID 删除用户
func DeleteUserByID(userID string) error {
	// 删除用户
	result := initConfig.GormDb.Where("id = ?", userID).Delete(&model.User{})
	if result.Error != nil {
		zap.L().Error("删除用户失败", zap.Error(result.Error))
		return result.Error
	}

	if result.RowsAffected == 0 {
		zap.L().Warn("未找到要删除的用户", zap.String("userID", userID))
		return gorm.ErrRecordNotFound
	}

	return nil
}

// CheckPassword 检验密码是否正确
func CheckPassword(hashedPassword, inputPassword string) error {
	// 确保加密密码不为空
	if hashedPassword == "" {
		zap.L().Error("数据库中对应账户的密码为空，无法验证密码")
	}

	// 使用 bcrypt 验证密码
	err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(inputPassword))
	if err != nil {
		zap.L().Error("无法验证密码是否正确", zap.Error(err))
		return err
	}
	return nil
}

// CheckUserExist 检查数据库中是否已有该账号
func CheckUserExist(account string) (bool, error) {
	var existingUser model.User
	err := initConfig.GormDb.Where("account = ?", account).First(&existingUser).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return false, nil
		} else {
			// 其他数据库错误
			zap.L().Error("数据库错误，无法检查数据库中是否已有该账号", zap.Error(err))
			return false, err
		}
	} else {
		zap.L().Info("该用户已经被添加", zap.String("账号：", account))
		return true, nil
	}
}

// EncryptPassword 加密密码
func EncryptPassword(password string) ([]byte, error) {
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		zap.L().Error("无法加密用户密码", zap.Error(err))
		return hashedPassword, err
	}
	return hashedPassword, nil
}

// CreateNewUser 创建新用户
func CreateNewUser(newUser model.User) error {
	err := initConfig.GormDb.Create(&newUser).Error
	if err != nil {
		zap.L().Error("无法在数据库中创建新用户", zap.Error(err))
		return err
	}
	return nil
}

// UpdateUser 更新用户信息
func UpdateUser(user *model.User) error {
	err := initConfig.GormDb.Save(user).Error
	if err != nil {
		zap.L().Error("无法更新用户信息", zap.Error(err))
		return err
	}
	return nil
}

// GetUserByIdFromSQL 手动执行 SQL 脚本获取单个用户
func GetUserByIdFromSQL(id string) (model.User, error) {
	// 定义基础 SQL 查询脚本
	query := `
		SELECT id, account, username, gender, phone, password, add_time, is_manager, department
		FROM users
		WHERE id = ?
	`

	// 定义参数
	args := []interface{}{id}

	var user model.User

	// 执行查询
	rows, err := initConfig.SqlDb.Query(query, args...)
	if err != nil {
		zap.L().Error("执行查询失败",
			zap.String("query", query),
			zap.String("id", id),
			zap.Error(err))
		return user, err
	}
	defer func() {
		if rows != nil {
			if closeErr := rows.Close(); closeErr != nil {
				zap.L().Error("关闭查询结果集失败",
					zap.String("query", query),
					zap.Error(closeErr))
			}
		}
	}()

	// 解析结果
	if rows.Next() {
		err := rows.Scan(
			&user.ID,
			&user.Account,
			&user.Username,
			&user.Gender,
			&user.Phone,
			&user.Password,
			&user.AddTime,
			&user.IsManager,
			&user.Department,
		)
		if err != nil {
			zap.L().Error("解析用户数据失败", zap.Error(err))
			return user, err
		}
		// 返回成功
		return user, nil
	}

	// 检查是否有错误
	if err := rows.Err(); err != nil {
		zap.L().Error("遍历查询结果时出错", zap.Error(err))
		return user, err
	}

	// 没有找到记录
	return user, gorm.ErrRecordNotFound
}

type UserListResult struct {
	Users      []model.ReturnUser
	TotalCount int
}

// GetUserListFromSQL 获取用户列表及总记录数（带分页、筛选、排序）
func GetUserListFromSQL(userInput struct {
	Sift   []string `json:"sift"`   // 筛选条件：男/女/部门
	Sort   string   `json:"sort"`   // 排序方式：升序/降序
	Search string   `json:"search"` // 搜索关键字：姓名/某个字
	Page   int      `json:"page"`   // 第几页
}) (UserListResult, error) {

	// 基础查询语句（用于获取用户列表）
	baseQuery := `
		SELECT id, username, gender, phone, department, add_time
		FROM users
		WHERE 1=1
	`

	// COUNT 查询语句（仅统计总数，不带 LIMIT/OFFSET）
	countQuery := `
		SELECT COUNT(*) 
		FROM users
		WHERE 1=1
	`

	// 分别维护两个参数列表：
	var argsCount []interface{} // 用于 COUNT 查询
	var argsPage []interface{}  // 用于主查询（含分页）

	// 解析筛选条件（性别和部门）
	var genders []string
	var departments []string

	for _, condition := range userInput.Sift {
		switch condition {
		case "男", "女":
			genders = append(genders, condition)
		default:
			departments = append(departments, condition)
		}
	}

	// 添加性别筛选到查询中
	if len(genders) > 0 {
		clause := " AND gender IN (" + placeholders(len(genders)) + ")"
		baseQuery += clause
		countQuery += clause
		argsCount = append(argsCount, convertToInterfaceSlice(genders)...)
		argsPage = append(argsPage, convertToInterfaceSlice(genders)...)
	}

	// 添加部门筛选到查询中
	if len(departments) > 0 {
		clause := " AND department IN (" + placeholders(len(departments)) + ")"
		baseQuery += clause
		countQuery += clause
		argsCount = append(argsCount, convertToInterfaceSlice(departments)...)
		argsPage = append(argsPage, convertToInterfaceSlice(departments)...)
	}

	// 添加搜索条件（用户名或电话模糊匹配）
	if userInput.Search != "" {
		searchClause := " AND (username LIKE ? OR phone LIKE ?)"
		baseQuery += searchClause
		countQuery += searchClause

		// 为每个 ? 提供一个参数值，共两个
		argsCount = append(argsCount,
			"%"+userInput.Search+"%",
			"%"+userInput.Search+"%",
		)
		argsPage = append(argsPage,
			"%"+userInput.Search+"%",
			"%"+userInput.Search+"%",
		)
	}

	// 添加排序逻辑
	if userInput.Sort == "添加时间升序" {
		baseQuery += " ORDER BY STR_TO_DATE(add_time, '%Y-%m-%d %H:%i:%s') ASC"
	} else if userInput.Sort == "添加时间降序" {
		baseQuery += " ORDER BY STR_TO_DATE(add_time, '%Y-%m-%d %H:%i:%s') DESC"
	} else {
		// 默认按添加时间降序
		baseQuery += " ORDER BY STR_TO_DATE(add_time, '%Y-%m-%d %H:%i:%s') DESC"
	}

	// 分页逻辑只作用于 baseQuery
	pageSize := 7
	if userInput.Page <= 0 {
		userInput.Page = 1
	}
	offset := (userInput.Page - 1) * pageSize
	baseQuery += " LIMIT ? OFFSET ?"
	argsPage = append(argsPage, pageSize, offset)

	// 执行 COUNT 查询
	var totalCount int
	err := initConfig.SqlDb.QueryRow(countQuery, argsCount...).Scan(&totalCount)
	if err != nil {
		zap.L().Error("执行计数查询失败",
			zap.String("query", countQuery),
			zap.Any("args", argsCount),
			zap.Error(err))
		return UserListResult{}, err
	}

	// 执行主查询
	rows, err := initConfig.SqlDb.Query(baseQuery, argsPage...)
	if err != nil {
		zap.L().Error("执行查询失败",
			zap.String("query", baseQuery),
			zap.Any("args", argsPage),
			zap.Error(err))
		return UserListResult{}, err
	}
	defer func() {
		if rows != nil {
			if closeErr := rows.Close(); closeErr != nil {
				zap.L().Error("关闭查询结果集失败", zap.Error(closeErr))
			}
		}
	}()

	// 解析结果
	var userList []model.ReturnUser
	for rows.Next() {
		var user model.ReturnUser
		err := rows.Scan(
			&user.ID,
			&user.Username,
			&user.Gender,
			&user.Phone,
			&user.Department,
			&user.AddTime,
		)
		if err != nil {
			zap.L().Error("解析用户数据失败", zap.Error(err))
			continue
		}
		userList = append(userList, user)
	}

	if err := rows.Err(); err != nil {
		zap.L().Error("遍历查询结果时出错", zap.Error(err))
		return UserListResult{}, err
	}

	return UserListResult{
		Users:      userList,
		TotalCount: totalCount,
	}, nil
}

// 辅助函数：类型转换工具（将 []string 转为 []interface{}）
func convertToInterfaceSlice[T ~string](s []T) []interface{} {
	res := make([]interface{}, len(s))
	for i, v := range s {
		res[i] = v
	}
	return res
}

// 辅助函数：生成占位符
func placeholders(n int) string {
	return strings.Repeat("?,", n)[:2*n-1]
}
